//The MIT License (MIT)
//
//Copyright (c) 2018 dote
//
//Permission is hereby granted, free of charge, to any person obtaining a copy of
//this software and associated documentation files (the "Software"), to deal in
//the Software without restriction, including without limitation the rights to
//use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
//the Software, and to permit persons to whom the Software is furnished to do so,
//subject to the following conditions:
//
//The above copyright notice and this permission notice shall be included in all
//copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
//FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
//COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
//IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
//CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

package com.github.dote.mio.filter.ext;
 

import java.io.Serializable;
import java.util.*;

public class Sort implements  Serializable {
    private static final long serialVersionUID = 5737186511678863905L;
    public static final Sort.Direction DEFAULT_DIRECTION;
    private Sort.Order order;

    public Sort(Sort.Order order) {
        this.order = order;
    }


    public Sort(String properties) {
        this(DEFAULT_DIRECTION, properties);
    }


    public Sort(Sort.Direction direction, String properties) {
        if (properties != null && !properties.isEmpty()) {
            this.order = new Order(direction,properties);
        } else {
            throw new IllegalArgumentException("You have to provide at least one property to sort by!");
        }
    }

    public Order getOrder() {
        return order;
    }

    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        } else if (!(obj instanceof Sort)) {
            return false;
        } else {
            Sort that = (Sort)obj;
            return this.order.equals(that.order);
        }
    }

    public int hashCode() {
        int result1 = 17;
        int result = 31 * result1 + this.order.hashCode();
        return result;
    }

    static {
        DEFAULT_DIRECTION = Sort.Direction.ASC;
    }

    public static class Order implements Serializable {
        private static final long serialVersionUID = 1522511010900108987L;
        private static final boolean DEFAULT_IGNORE_CASE = false;
        private final Sort.Direction direction;
        private final String property;
        private final boolean ignoreCase;

        public Order(Sort.Direction direction, String property) {
            this(direction, property, false);
        }

        public Order(String property) {
            this(Sort.DEFAULT_DIRECTION, property);
        }

        private Order(Sort.Direction direction, String property, boolean ignoreCase) {
            if (!hasText(property)) {
                throw new IllegalArgumentException("Property must not null or empty!");
            } else {
                this.direction = direction == null ? Sort.DEFAULT_DIRECTION : direction;
                this.property = property;
                this.ignoreCase = ignoreCase;
            }
        }

        public static boolean hasText(CharSequence str) {
            if (!(str != null && str.length() > 0)) {
                return false;
            } else {
                int strLen = str.length();

                for(int i = 0; i < strLen; ++i) {
                    if (!Character.isWhitespace(str.charAt(i))) {
                        return true;
                    }
                }

                return false;
            }
        }

        /** @deprecated */
        @Deprecated
        public static List<Sort.Order> create(Sort.Direction direction, Iterable<String> properties) {
            List<Sort.Order> orders = new ArrayList();
            Iterator i$ = properties.iterator();

            while(i$.hasNext()) {
                String property = (String)i$.next();
                orders.add(new Sort.Order(direction, property));
            }

            return orders;
        }

        public Sort.Direction getDirection() {
            return this.direction;
        }

        public String getProperty() {
            return this.property;
        }

        public boolean isAscending() {
            return this.direction.equals(Sort.Direction.ASC);
        }

        public boolean isIgnoreCase() {
            return this.ignoreCase;
        }

        public Sort.Order with(Sort.Direction order) {
            return new Sort.Order(order, this.property);
        }

        public Sort withPropery(String property) {
            return new Sort(this.direction, property);
        }

        public Sort.Order ignoreCase() {
            return new Sort.Order(this.direction, this.property, true);
        }

        public int hashCode() {
            int result1 = 17;
            int result = 31 * result1 + this.direction.hashCode();
            result = 31 * result + this.property.hashCode();
            return result;
        }

        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            } else if (!(obj instanceof Sort.Order)) {
                return false;
            } else {
                Sort.Order that = (Sort.Order)obj;
                return this.direction.equals(that.direction) && this.property.equals(that.property);
            }
        }

        public String toString() {
            return String.format("%s: %s", this.property, this.direction);
        }
    }

    public static enum Direction {
        ASC,
        DESC;

        private Direction() {
        }

        public static Sort.Direction fromString(String value) {
            try {
                return valueOf(value.toUpperCase(Locale.US));
            } catch (Exception var2) {
                throw new IllegalArgumentException(String.format("Invalid value '%s' for orders given! Has to be either 'desc' or 'asc' (case insensitive).", value), var2);
            }
        }

        public static Sort.Direction fromStringOrNull(String value) {
            try {
                return fromString(value);
            } catch (IllegalArgumentException var2) {
                return null;
            }
        }
    }
}
